home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / OpenDoc / CreditNow! / CreditNow! Source / $Utilities / TextField.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-01  |  10.5 KB  |  431 lines  |  [TEXT/MPCC]

  1. /*
  2.     File:        TextField.cpp
  3.  
  4.     Contains:    TextEdit class to contain TextEdit from Toolbox
  5.  
  6.     Written by:    Andrew Taylor
  7.  
  8.     Theory of Operation:
  9.         Quick and dirty wrapper for TextEdit
  10.         
  11.     Copyright:    © 1995 by Appropriate Solutions, Inc., all rights reserved.
  12.  
  13.     Change History (most recent first):
  14.  
  15.  
  16.          <0>    started
  17. */
  18.  
  19. #ifndef _TEXTFIELD_
  20. #include "TextField.h"
  21. #endif
  22.  
  23. #ifndef __DIALOGS__
  24. #include <Dialogs.h>
  25. #endif
  26.  
  27. const char kRightArrow    = 0x1D;
  28. const char kLeftArrow    = 0x1C;
  29. const char kUpArrow        = 0x1E;
  30. const char kDownArrow    = 0x1F;
  31.  
  32.  
  33. //========================================================================================
  34. // TextField
  35. //========================================================================================
  36.  
  37. TextField::TextField()
  38. {
  39.     fTheTE = nil;
  40.     fMaxChars = 0;
  41.     fIdentifier = 0;
  42.     fAnchorPoint = 0;
  43. }
  44.  
  45. //----------------------------------------------------------------------------------------
  46.  
  47. TextField::~TextField()
  48. {
  49. }
  50.  
  51. //----------------------------------------------------------------------------------------
  52.  
  53. void TextField::InitTextField(ODTypeToken id, short maxChars, Rect *destRect)
  54.     // id is the identifier for this field
  55.     // destRect is converted to dest, view and passed to TENew.
  56.     // maxChars is the maximum characters allowed in the field
  57. {
  58.     Rect dest, view;
  59.     
  60.     dest = *destRect;
  61.     view = *destRect;
  62.     
  63.     ::InsetRect(&dest, 2, 2);
  64.     ::InsetRect(&view, 2, 2);
  65.     if (nil == fTheTE)
  66.         fTheTE = ::TENew(&dest, &view);
  67.     else
  68.     {
  69.         (*fTheTE)->destRect = dest;
  70.         (*fTheTE)->viewRect = view;
  71.         ::InvalRect(&view);
  72.     }
  73.     fIdentifier = id;
  74.     fMaxChars = maxChars;
  75. }
  76.  
  77. //----------------------------------------------------------------------------------------
  78.  
  79. void TextField::ReleaseTextField()
  80.     // dispose of TextEdit record
  81. {
  82.     if (fTheTE)
  83.         ::TEDispose(fTheTE);
  84.     fTheTE = nil;
  85. }
  86.             
  87.  
  88. //----------------------------------------------------------------------------------------
  89.  
  90. Boolean TextField::KeyStroke(char inKey, short modifiers)
  91.     // enter keystroke into TE record
  92.     // returns true if keystroke accepted
  93. {
  94.     Boolean result = false;
  95.     short    length;
  96.     short    selStart = (*fTheTE)->selStart;
  97.     short    selEnd = (*fTheTE)->selEnd;
  98.     
  99.     if ( selEnd == selStart )
  100.         fAnchorPoint = selStart;
  101.  
  102.     if (modifiers & shiftKey)
  103.     {
  104.         switch (inKey)
  105.         {
  106.             case kRightArrow:
  107.             {
  108.                 if (fAnchorPoint < selStart)
  109.                     selStart += 1;
  110.                 else
  111.                     selEnd += ( selEnd < 32000) ? 1 : 0;
  112.                 ::TESetSelect(selStart, selEnd, fTheTE);
  113.                 result = true;
  114.                 break;
  115.             }
  116.  
  117.             case kLeftArrow:
  118.             {
  119.                 if (fAnchorPoint < selEnd)
  120.                     selEnd -= 1;
  121.                 else
  122.                     selStart -= ( selStart > 0) ? 1 : 0;
  123.                 ::TESetSelect(selStart, selEnd, fTheTE);
  124.                 result = true;
  125.                 break;
  126.             }
  127.         }
  128.     }
  129.     if (modifiers & cmdKey)
  130.         return(result);
  131.     if (!result)
  132.     {
  133.             // allow keystrokes if max chars and there is a selection range.
  134.         length = (*fTheTE)->teLength - ((*fTheTE)->selEnd - (*fTheTE)->selStart);
  135.         if ( (length < fMaxChars) || ((inKey < ' ') || (inKey > 'z')) )
  136.         {
  137.             //    Strange TextEdit bug remedy... (Thanks to Patrick Doane)
  138.             (*fTheTE)->clikStuff = -1;    
  139.             ::TEKey(inKey, fTheTE);
  140.             result = true;
  141.         }
  142.     }
  143.     return(result);
  144. }
  145.  
  146. //----------------------------------------------------------------------------------------
  147.  
  148. Boolean TextField::ContainsPoint(Point where)
  149.     // Determines if point is contained within the view rect.
  150. {
  151.     return( PtInRect(where, &(**fTheTE).viewRect) );
  152. }
  153.  
  154. //----------------------------------------------------------------------------------------
  155.  
  156. void TextField::MouseClick(Point where, EventRecord *event)
  157.     // pass mouse click to TextEdit
  158. {
  159.     ::TEClick(where, (event->modifiers & shiftKey) == shiftKey, fTheTE);
  160.     fAnchorPoint = (*fTheTE)->selStart;
  161. }
  162.  
  163. //----------------------------------------------------------------------------------------
  164.  
  165. void TextField::Draw(RgnHandle invalRgn)
  166.     // draw frame box
  167.     // update TextEdit display
  168. {
  169.     Rect rct = (**fTheTE).viewRect;
  170.     ::InsetRect(&rct, -2, -2);
  171.     ::FrameRect(&rct);
  172.     ::TEUpdate(&(**invalRgn).rgnBBox, fTheTE);
  173. }
  174.             
  175. //----------------------------------------------------------------------------------------
  176.  
  177. Handle TextField::GetTextHandle(long *usedLength)
  178.     // retrieve TextEdit record handle
  179. {
  180.     *usedLength = (**fTheTE).teLength;
  181.     return (**fTheTE).hText;
  182. }
  183.             
  184. //----------------------------------------------------------------------------------------
  185.  
  186. Handle TextField::GetSelectedPtr(Ptr *data, long *length)
  187.     // set ptr to selected text. Set length of selected text.
  188.     // caller is expected to lock and unlock handle if use of ptr
  189.     // will cause memory move.
  190. {
  191.     *length = ((**fTheTE).selEnd - (**fTheTE).selStart);
  192.     *data = ( &( (*(**fTheTE).hText)[(**fTheTE).selStart] ) );
  193.     return((**fTheTE).hText);
  194. }
  195.             
  196. //----------------------------------------------------------------------------------------
  197.  
  198. void TextField::SetSelection(long start, long end)
  199.     // set the selection range
  200. {
  201.     ::TESetSelect(start, end, fTheTE);
  202.     fAnchorPoint = start;
  203. }
  204.             
  205. //----------------------------------------------------------------------------------------
  206.  
  207. void TextField::GetText(Str255 str)
  208.     // retrieve text from TextEdit record
  209. {
  210.     ::GetDialogItemText((**fTheTE).hText, str);
  211. }
  212.  
  213. //----------------------------------------------------------------------------------------
  214.  
  215. void TextField::SetText(Str255 str)
  216.     // load TextEdit record with text
  217. {
  218.     ::TESetText( (Ptr)&str[1], (long)str[0], fTheTE);
  219. }
  220.             
  221. //----------------------------------------------------------------------------------------
  222.  
  223. Boolean TextField::Validate()
  224.     // check for valid field contents. Display failure reason to user
  225.     // return true for good contents, false for bad.
  226. {
  227.     return(true);
  228. }
  229.  
  230. //----------------------------------------------------------------------------------------
  231.  
  232. void TextField::Activate()
  233.     // make this the active TE record
  234. {
  235.     ::TEActivate(fTheTE);
  236. }
  237.  
  238. //----------------------------------------------------------------------------------------
  239.  
  240. void TextField::Deactivate()
  241.     // deactivate TE record
  242. {
  243.     ::TEDeactivate(fTheTE);
  244. }
  245.  
  246. //----------------------------------------------------------------------------------------
  247.  
  248. void TextField::Idle()
  249.     // do some idle time.
  250. {
  251.     ::TEIdle(fTheTE);
  252. }
  253.  
  254.             
  255. //----------------------------------------------------------------------------------------
  256.  
  257. void TextField::Cut()
  258. {
  259.     ::TECut(fTheTE);
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263.  
  264. void TextField::Copy()
  265. {
  266.     ::TECopy(fTheTE);
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270.  
  271. void TextField::Paste()
  272. {
  273.     ::TEPaste(fTheTE);
  274. }
  275.  
  276. //----------------------------------------------------------------------------------------
  277.  
  278. void TextField::Clear()
  279. {
  280.     ::TEDelete(fTheTE);
  281. }
  282.  
  283. //----------------------------------------------------------------------------------------
  284.  
  285. Boolean TextField::HaveSelection()
  286. {
  287.     return( ((**fTheTE).selStart != (**fTheTE).selEnd) );
  288. }
  289.  
  290.  
  291. //========================================================================================
  292. // LabeledTextField
  293. //========================================================================================
  294.  
  295. LabeledTextField::LabeledTextField()
  296. {
  297.     fLabel[0] = 0;
  298. }
  299.  
  300. //----------------------------------------------------------------------------------------
  301.  
  302. LabeledTextField::~LabeledTextField()
  303. {
  304. }
  305.  
  306. //----------------------------------------------------------------------------------------
  307.  
  308. void LabeledTextField::InitTextField(ODTypeToken id, short maxChars, short lblWidth, Rect *destRect, Str255 str)
  309.     // id is the identifier for this field
  310.     // destRect is converted to dest, view and passed to TENew.
  311.     // maxChars is the maximum characters allowed in the field
  312. {
  313.     fRect = *destRect;
  314.     destRect->left += lblWidth;
  315.     if (destRect->left >= destRect->right)            // nuff room for edit and label?
  316.         destRect->left = destRect->right - lblWidth/2;    //let the fields fight it out
  317.     ::BlockMove(&str[0], &fLabel[0], str[0]+1);
  318.  
  319.     TextField::InitTextField(id, maxChars, destRect);
  320. }
  321.  
  322. //----------------------------------------------------------------------------------------
  323.  
  324. void LabeledTextField::Draw(RgnHandle invalRgn)
  325. {
  326.         // place pen at left of field, up a little from the bottom
  327.     ::MoveTo(fRect.left, fRect.bottom - 6 );    // rgac 2);
  328.     ::DrawString(fLabel);
  329.     TextField::Draw(invalRgn);
  330. }
  331.  
  332.  
  333.  
  334. //========================================================================================
  335. // TextFieldLink
  336. //========================================================================================
  337.  
  338.  
  339. TextFieldLink::TextFieldLink( )
  340. {
  341.     fTextField = kODNULL;
  342.     fPrev  = this;
  343.     fNext  = this;
  344. }
  345.  
  346. //----------------------------------------------------------------------------------------
  347.  
  348. TextFieldLink::TextFieldLink( TextField *field, TextFieldLink *list )
  349. {
  350.     fTextField = field;
  351.     fPrev  = list;
  352.     fNext  = list->fNext;
  353.     list->fNext  = this;
  354.     fNext->fPrev = this;
  355. }
  356.  
  357. //----------------------------------------------------------------------------------------
  358.  
  359. TextFieldLink::~TextFieldLink( )
  360. {
  361.     if ( fPrev )
  362.         fPrev->fNext = fNext;
  363.     if ( fNext )
  364.         fNext->fPrev = fPrev;
  365. }
  366.  
  367.  
  368. //========================================================================================
  369. // TextFieldList
  370. //========================================================================================
  371.  
  372. TextFieldList::TextFieldList()
  373. {
  374.     fTextField = kODNULL;
  375.     fPrev = kODNULL;
  376.     fNext = this;
  377. }
  378.  
  379. //----------------------------------------------------------------------------------------
  380.  
  381. TextFieldList::~TextFieldList( )
  382. {
  383.     // Delete all links:
  384.     while ( fNext != this )
  385.         delete fNext;
  386. }
  387.  
  388. //----------------------------------------------------------------------------------------
  389.  
  390. void TextFieldList::Add( TextField *field )
  391. {
  392.     new TextFieldLink(field,this);
  393.     // The new link has already hooked itself into my chain so I don't need to
  394.     // remember it elsewhere.
  395. }
  396.  
  397. //----------------------------------------------------------------------------------------
  398.  
  399. void TextFieldList::Remove( TextField *field )
  400. {
  401.     TextFieldLink *link;
  402.     for ( link = this->First(); link->GetTextField(); link = link->Next() ) {
  403.         if ( link->GetTextField() == field ) {
  404.             delete link;
  405.             return;
  406.         }
  407.     }
  408.  
  409.     DebugStr("\pCouldn't find field");
  410. }
  411.  
  412. //----------------------------------------------------------------------------------------
  413.  
  414. void TextFieldList::Add(ODTypeToken id, short maxChars, Rect *destRect)
  415. {
  416.     TextField *aField = new TextField();
  417.     aField->InitTextField(id, maxChars, destRect);
  418.     this->Add(aField);
  419.  
  420. }
  421.  
  422. //----------------------------------------------------------------------------------------
  423.  
  424. void TextFieldList::Add(ODTypeToken id, short maxChars, short lblWidth, Rect *destRect, Str255 label)
  425. {
  426.     LabeledTextField *aField = new LabeledTextField();
  427.     aField->InitTextField(id, maxChars, lblWidth, destRect, label);
  428.     this->Add(aField);
  429.  
  430. }
  431.